<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Document</title></head><body></body></html>
<script>
//每一条路都是正确的路 一切都可能是另一种模样 而且具有同等重要的意义 
//Every path is the right path. Everything could have been anything else. and would have just this much meaning.



                                                            // 基本函数定义 //
//______________________________________________________________________________________________________________________________________
    //函数相当于一个工具  定义函数
    //TypeScript里定义函数跟JavaScript稍微有些不同
        //需要注意的是：
            // 1声明（定义）函数必须加 function 关键字；
            // 2函数名与变量名一样，命名规则按照标识符规则；
            // 3函数参数可有可无，多个参数之间用逗号隔开；
            // 4每个参数参数由名字与类型组成，之间用分号隔开；
            // 5函数的返回值可有可无，没有时，返回类型为 void；
            // 6大括号中是函数体。

            //ts中的函数约束 有函数本身的参数约束 返回值约束
            //和函数本身赋值的变量的约束  
            //可采用重载的方式才支持联合类型的函数关系 

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                          
                                                            // 3种函数的定义方式 // 
        //函数声明法 (声明式类型的函数)
        //函数声明法创建函数是最常用的函数定义法使用function关键字和函数名去定义一个函数 
            function add(n1:number,n2:number):number{
               return n1+n2   
            }
            console.log(add(1,2))  //3
            //demo+
            //对函数参数进行约束 &返回类型约束(is number类型)
            function funType(name:string,age:number):number{
                return age 
            }
            var ageNum:number = funcType("王钩子",18)
            //demo++
            //如果函数参数不确定的情况下
            function funcType2(name:string,age:number,sex?:string):number{
                return age
            }
            var ageNum2:number = function("张狗",18,"男")
                                                    //参3为 可选可不选 ?存疑
//——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
        //函数表达式
        //函数表达式是将一个函数赋值给一个变量，这个变量名就是函数名，  
        //通过变量名就可以调用这个函数了，    
        //注意！  这种方式定义的函数，必须在定义之后使用，
        //demo   中等号右边的函数没有函数名，称为匿名函数。   
            var add = function(n1:number,n2:number):number{
                 return n1+n2
             }
            console.log(add(1,4))  //5

//——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
        //箭头函数 简写方式 
        //即es6 新增的函数定义方式
        //TypeScript 语言是完全支持 ES6 语法的。箭头函数定义的函数一般都用于回调函数中。
        var add = (n1:number,n2:number):number =>{
         return n1+n2
         }
        // console.log(add(1,4))     //5


//______________________________________________________________________________________________________________________________________    
    //demo      
        //function searchXiaoJieJie(age:number):string{
        //     return '找到了'+age+'岁的小姐姐' 
        // }
        // var age:number = 18
        // var result:string = searchXiaoJieJie(age)
        // console.log(result)     //找到了18岁的小姐姐 

    //形参的使用 
        //函数定义的时候写的参数是形参。从字面意义上我们可以看出，形参就是形式上的参数。
        //我们定义了形参也就规定了此函数的 参数个数&参数类型，规范了函数。    
            //function searchXiaoJieJie(age:number):string{
            //     return '找到了'+age+'岁的小姐姐' 
            // }
            //这个函数，就定义了一个形参，它的类型是数值类型。

    //实参的使用
        //调用函数时传递的具体值就是实参。
        //实参就是真实的参数，在使用的时候，具体真实传递过去的就是实参，比如18，20，22，这些具体的参数就是实参。
      //实参在真实使用时才传递
            //var result:string = searchXiaoJieJie(age)
        //在函数调用的时候，我们需要按照形参的规则传递实参，
        //有几个形参就要传递几个实参，并且每一个实参的类型要与对应的形参类型一致。


//ts里面的函数___________________________________________________________________________________________________________________________   
    //函数的形参分为3种 
    //1可选形参、2默认形参、3剩余参数形参等。
     //1.有可选参数的函数
        //可选参数，就是我们定义形参的时候，可以定义一个可传可不传的参数。这种参数，在定义函数的时候 通过?标注
        //demo
            function searchXiaoJieJie2(age:number,stature?:string):string{
             let yy:string = ''
             yy = '找到了'+age+'岁'
             if(stature !=undefined){
                 yy = yy + stature
             }
             return yy+'的小姐姐'
             }
             var result:string  =  searchXiaoJieJie2(22,'大长腿')
             console.log(result)
//______________________________________________________________________________________________________________________________________    
    //2.有默认参数的函数 
        //函数不传递参数的时候，他会给我们一个默认值，而不是udefined
        //我们改造上边的函数，也是两个参数，但是我们把年龄和身材都设置默认值 给两个默认值 18,大x
            function searchXiaoJieJie2(age:number=18,stature:string='大胸'):string{
                 let yy:string = ''
            yy = '找到了'+age+'岁'
                 if(stature !=undefined){
                     yy = yy + stature
                 }
                 return yy+'的小姐姐'
            }
            var result:string  =  searchXiaoJieJie2()
            console.log(result)    //找到了19岁大x的小姐姐
        
//______________________________________________________________________________________________________________________________________    
    //3.有剩余参数的函数
        //需求，我传递给函数的参数个数不确定
        //注意，剩余参数就是形参是一个数组，传递几个实参过来都可以直接存在形参的数组中
        function searchXiaoJieJie3(...xuqiu:string[]):string{
            let  yy:string = '找到了'
            for (let i =0;i<xuqiu.length;i++){
             yy = yy + xuqiu[i]
             if(i<xuqiu.length){
                 yy=yy+'、'
             }
          }
            yy=yy+'的小姐姐'
            return yy
          }
        var result:string  =  searchXiaoJieJie3('22岁','大长腿','瓜子脸','水蛇腰')
        console.log(result)    //找到了22岁、大长腿、瓜子脸、水蛇腰、的小姐姐
                    

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                             // 函数中变量的作用域 //
                                             
        // 每个变量都有一个起作用的范围，这个范围就是变量的作用域。
        // 在TypeScript语言中变量作用域，划分是以函数为标准的。
        // 定义在函数内部的变量&定义在函数外部的变量是不一样的 ， 起作用的区域也不一样         
         //demo1
            //   function zhengXing():void{
            //         var yangzi = '刘德华'
            //         console.log(yangzi)
            //     }
            //     zhengXing()
            //     console.log(yangzi)    //报错
            
//————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
    //局部变量：函数体内 定义的变量就是局部变量。
    //全局变量: 函数体外 定义的变量就是全局变量。  
          //demo2 
             // var yanzi = "刘德华"           //这时候yangzi变量是全局的，所以在函数内也可以调用，在函数外也可以调用。
             //function zhengxing():void{
                // console.log("我变成"+yanzi) //我变成刘德华
            // } 
            //zhengxing()
            //console.log(yanzi)               //刘德华
//———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

    //局部变量&全局变量重名时 
      //在函数体内是局部变量起作用；如果重名，就有变量提升
          //demo3
            //   var yangzi:string = '刘德华'
            //     function zhengXing():void{
            //         var yangzi:string = '马德华'
            //         console.log('技术胖整形成了'+yangzi+'的样子')      //马德华
            //     }
            //     zhengXing()
            //     console.log(yangzi)   //刘德华


    //变量提升
            //var yangzi:string = '刘德华'
            // function zhengXing():void{
            //     console.log('技术胖整形成了'+yangzi+'的样子')         //技术胖整形成了undefined的样子 
            //     var yangzi:string = '马德华'                          //产生这个结果的原因就是变量提升，他的真实代码是这样的。

            //     console.log('技术胖整形成了'+yangzi+'的样子')
            // }
            // zhengXing()
            // console.log(yangzi)
                //产生这个结果的原因就是变量提升，他的真实代码是这样的。
                //当内部声明了和全局的变量同名时，就会出现变量提升的效果，声明语句会提升到函数的第一句。这就是著名的变量提升效果。
            // var yangzi:string = '刘德华'
            // function zhengXing():void{
            //     var  yangzi:string                                     //变量提升  
            //     console.log('技术胖整形成了'+yangzi+'的样子')
            //     yangzi = '马德华'
            //     console.log('技术胖整形成了'+yangzi+'的样子')
            // }
            // zhengXing()
            // console.log(yangzi)

    //let关键字变量的作用域
            //在早期的js的变量作用域只有全局&局部，并且以函数划分的
            //但在其他语言中作用域的划分时以一对大括号作为界限的 
            //容易内存溢出 所以在es6中推出let
            //使用let关键字的变量就是一个块级作用域变量 

            //demo            
                // function zhengXing():void{
                // var yangzia:string = '刘德华'
                // {
                //         let  yangzib:string = '小沈阳'
                //         console.log('技术胖整形成了'+yangzib+'的样子')  //技术胖整形成了小沈阳的样子
                // }

                //     console.log('技术胖整形成了'+yangzia+'的样子')      //技术胖整形成了刘德华的样子
                //     console.log('技术胖整形成了'+yangzib+'的样子')      //报错 访问不到 let
                // } 
                // zhengXing()    




//ts函数参数和返回值类型的定义  
        //下面代码有一个小坑的，就是我们并没有定义getTotal的返回值类型，虽然TypeScript可以自己推断出返回值是number类型。
        //但是如果这时候我们的代码写错了，比如写程了下面这个样子。
        function getTotal(one:number,two:number){
             return one+two
        }
        const total = getTotal(1,2);
        //比如返回值这样的
        function getTotal(one: number, two: number) {
             return one + two + "";
        }
        const total = getTotal(1, 2);
        //这时候total的值 就不是number类型了
        //可以给total类型注释 比如 但是还是不够明智  
        const total:number = getTotal(1,2);
        //因为错误的根本是getTotal函数的错误 所以合适的做法是给函数的返回值加上 类型注释 代码如下 
        function getTotal(one:number,two:number):number{
            return one + two;
        }
        const total = getTotal(1,2)
        //至此 代码较为严谨 

//函数无返回值时定义方法 
        //有时候函数没有返回值 定义一个sayHellow的函数 并没有返回值 
        function sayHellow(){
            console.log("hellow world")
        }
        //这个没有返回值的函数 我们就可以给他一个类型注释void 代表没有任何返回值  
        function sayHellow():void{
            console.log("hellow world")
        }
        //注意这样定义后 再加入任何返回值 程序都会报错 

//never返回值类型 
        //如果一个函数永远也执行不完 就可以定义返回值为never  
        //(即执行时，抛出异常，这时候就无法执行完了)
        function errorFunction():never{
            throw new Error();
            console.log("hellow World")
        }
        //还有一种就是一直循环 即死循环 这样也运行不完 
        function forNever():never{
            while(true){}
            console.log("hellow World")
        }

//函数参数为对象(解构)时 
        //dmeo 正确的写法 
        function add({one,two}:{one:number,two:numebr}):number{
            return one+two;
        }
        const three = add({one:1,two:2});
        //注意坑 如果参数是对象 并且里面只有一个属性时 
        function getNumber({one}:{one:numebr}):number{
            
        }


























</script>